Implementation notes for the !Menu CSE of !ResEd
================================================

Contents
--------

1  Drag-N-Drop
2  Moving/Copying selected entries from src to dst (dropped at position p)
3  Menu layout & rendering
4  Responding to HelpRequest messages
  4.1  Dialogue box
  4.2  Menu
  4.3  Editing window
  4.4  Palette window


1  Drag-N-Drop
--------------

1) We don't accept DataSave except for getting the name of an object.
   External transfers are not available.  Internal transfers (between
   Menu windows of the same invocation of the CSE) are provided.

2) The Message_Dragging protocol is not sent or claimed.  Auto-scroll etc
   is done internally only.

These decisions can be revisited later if necessary, the code to
handle them will slot in fairly easily.  However note that doing an
external drag-n-drop interaction using the Resource file format,
whilst easy enough to code, will not permit separators to be dragged
out on their own (because there is no way to represent that in the
Menu object data format).


2  Moving/Copying selected entries from src to dst (dropped at position p)
--------------------------------------------------------------------------

(Src can be the same as dst)

1) MOVING:
     Take the selected entries out of src and link them onto a temporary list
     "tmp"
     Ensure that src is still validly linked up.  Leave the Y coords in src
     alone for now.
   COPYING:
     Make copies of the selected entries in src and link them onto a
     temporary list "tmp".

2) Disambiguate the component IDs of tmp resp. dst.
     (No-op if moving && dst == src)

3) Determine insertion point within "dst".  This is the entry after which to
   add the tmp list (NULL meaning "after the title").  It is done by walking
   dst as follows:-

        MenuEntryPtr after = NULL;
        for (entry = dst->entries; entry; entry = entry->next)
        {
            if (p.y is above the centreline of entry)
                break;
            after = entry;
        }

4) Deselect all in dst.

5) Splice tmp into dst after "after" (at head is "after" is NULL).
   Ensure that the entries end up selected and that dst->numentries and
   dst->numselected are correct.  Update/redisplay any editing dboxes
   that are owned by the incoming objects (this will only happen on
   moves).

6) Recalculate sizes and layout of src (and dst if different to src)

7) Set input focus to dst


3  Menu layout & rendering
--------------------------

Need to take into account outline fonts, and the right-justification of
keyboard shortcuts.

Re-calculate the width of menu items (and hence width of whole menu, by
adding room for tick & arrow) each time any of the following happen:-

    An item is added or removed (including moving items around)
    A dotted line is added/removed
    An item's text or sprite is changed
    Title of the menu is changed
    Title of the window is changed
    The mode changes
    The system font changes
    The user *iconsprites a sprite file

In each case, increase/decrease  window extent if necessary before redrawing.
Simply make the extent enough to give a nice border around the menu.

Calculate the height of the menu by adding up all the item heights, and
including the title, the borders, and any dotted lines.

Calculate the width of the menu by finding all the item widths (see below)
and picking the biggest.  Then add room for the border, tick and arrow.

While doing this pass we will fill in some vital information about
each menu item; its position, size, etc - for the plotting code and
mouse hit code to use.

When we calculate the width of the menu items, use a similar piece of
code to TGR's one, but use Font_StringWidth (or the new wimp's special
trick whatever it is*) if an outline font is in use.  Just count the
length of the whole string (don't worry about double-space convention
for now - just count them, and the keycut, too.  We can perhaps make
this more sophisticated later if needed).

Height of menu entries is fixed, as is the height of a dotted line.

 [* (MFC): The code calls the function wimp_string_width(..) - found in
      common.c.wimp - which uses Wimp_TextOp if available, and otherwise
      simply assumes each character is 16 OS units wide.  ]


4  Responding to HelpRequest messages
-------------------------------------

The following contexts are distinguished, each giving rise to a "base" help
token as shown. If there is no entry for the base token in the Messages file,
then simpler derived tokens are looked up until one is found to be present:
the priority order is as shown.


4.1  Dialogue box
-----------------

  Token:  Hlp.W<n>.<icon-name>     - if pointer over named icon
          Hlp.W<n>                 - if pointer not over named icon

    where  <n> is the registered window type:

                 2  menudbox
                 3  entrydbox

     and   <icon-name> is the name of the icon.

  Examples:  Hlp.W2.TITLE,  Hlp.W2

  Lookup order:  Hlp.W<n>.<icon-name>
                 Hlp.<icon-name>
                 Hlp.ADJ_UP       - if <icon-name> ends in ADJ_UP
                 Hlp.ADJ_DOWN     - if <icon-name> ends in ADJ_DOWN
                 Hlp.MAX          - if <icon-name> ends in MAX
                 Hlp.W<n>

    The special cases (ADJ_UP, etc.) make it possible, for example, to supply
    a single help response for all up adjuster arrows: the base token might
    be Hlp.W2.TITLEMAX_ADJ_UP with the first match in the list above being
    Hlp.ADJ_UP.

  
4.2  Menu
---------

  Token:  Hlp.M<n>.<h1>.<h2>...

    where  <n> is the registered menu type:

                 1  editing window menu

     and   <h1>, <h2>, ... is the "hit list" which identifies the entry
            chosen from the menu (the first entry has index 0).

  Lookup order:  Hlp.M<n>.<h1>.<h2> ... <hn-1><hn>
                 Hlp.M<n>.<h1>.<h2> ... <hn-1>
                           ...
                 Hlp.M<n>.<h1>
                 Hlp.M<n>


4.3  Editing window
-------------------

  Token:  Hlp.E            - if pointer not over menu
          Hlp.MT           - if pointer over menu's titlebar

    If the pointer is over a menu entry with component ID <id>, then the help
    response text is made up of two parts:

      a) The result of looking up the token Hlp.EE and interpreting it as a
         format string for a printf(..) call whose second argument is <id>;

      b) The result of looking up the token Hlp.EES (if the menu entry is
         selected) or Hlp.EEN (if the entry is not selected).

    If the pointer is over a separator, the help response text is made up of
    two parts as follows:

      a) The result of looking up the token Hlp.ES;

      b) The result of looking up the token Hlp.ESS (if the separator is
         selected) or Hlp.ESN (if the separator is not selected).

  Example:

    Suppose the pointer is over a selected menu entry with component ID &10,
    and that the Messages file contains the following entries:

        Hlp.EE:This is a menu entry with ID = &%x.
        Hlp.EEN:\Dreposition.
        Hlp.EES:\Dmove selection.

    Then the help response text will be:

        This is a menu entry with ID = &10. Drag SELECT to move selection.


4.4  Palette window
-------------------

  Token:  Hlp.P            - if pointer not over menu entry or separator

    If the pointer is over a menu entry or separator, then the help response
    text is made up of two parts:

      a) The result of looking up the token Hlp.PE (if the pointer is over a
         menu entry) or Hlp.PS (if the pointer is over a separator);

      b) The result of looking up the token Hlp.PIS (if the menu entry is
         selected) or Hlp.PIN (if the entry is not selected).
